package com.mentorgen.tools.util.profile.bundle;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

import com.mentorgen.tools.util.profile.bundle.BundleContainer.BundleType;
import com.mentorgen.tools.util.profile.bundle.scheduler.SchedulerIF;

public class OSGiServiceScheduler implements Runnable, BundleListener {
	
	private BundleContext context;
	private Map<String, BundleContainer> containerMap;
	private static int swapCounter = 0;
	
	public static final int DEFAULT_SWAP_TIME = 60000;
	public static final String SWAP_ALG = "ca.ubc.jip.profiler.replacement.algorithm";
	public static final String SWAP_INTERVAL = "ca.ubc.jip.profiler.replacement.swap.interval";
	public static final String SCHEDULER_PACKAGE = "com.mentorgen.tools.util.profile.bundle.scheduler.";
	
	private SchedulerIF scheduler;
	
	public OSGiServiceScheduler(BundleContext _context){
		
		this.context = _context;
		containerMap = new HashMap<String, BundleContainer>();
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public void run() {
		
		initBundleContainer();
		initScheduler();
		
		while (true){
			
			try{
				List<BundleContainer> containerList = scheduler.schedule(containerMap);
				
				for (BundleContainer container : containerList)
					container.swap(true);

				if (context.getProperty(OSGiServiceScheduler.SWAP_INTERVAL) != null)
					Thread.sleep(Integer.valueOf(context.getProperty(OSGiServiceScheduler.SWAP_INTERVAL)).intValue());
				else
					Thread.sleep(DEFAULT_SWAP_TIME);
				
			}catch(Exception e){
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
		}
	}
	
	
	@SuppressWarnings("unchecked")
	private void initScheduler(){
		
		try {
			
			Class<SchedulerIF> clazz =	(Class<SchedulerIF>) Class.forName(
					OSGiServiceScheduler.SCHEDULER_PACKAGE + 
					context.getProperty(OSGiServiceScheduler.SWAP_ALG));
			scheduler = clazz.newInstance();
			
		} catch (ClassNotFoundException e) {
			System.err.println("Scheduler Class Not Found: " + e.getMessage());
		} catch (InstantiationException e) {
			System.err.println("Scheduler Class Cannot Be Instantiated: " + e.getMessage());
		} catch (IllegalAccessException e) {
			System.err.println("Instantiation Access Not Allowed " + e.getMessage());
		}
	}
	
	private void initBundleContainer(){
		for (Bundle bundle : context.getBundles())
			if (BundleFilter.include(bundle.getSymbolicName()))
				containerMap.put( bundle.getSymbolicName(), new BundleContainer(context, bundle));
		context.addBundleListener(this);
	}
	
	@Override
	public void bundleChanged(BundleEvent event) {
		
		switch(event.getType()){
		case BundleEvent.STARTED:
			if (!containerMap.containsKey(event.getBundle().getSymbolicName()) &&
					!BundleContainer.isInstrumented(event.getBundle()) && 
					BundleFilter.include(event.getBundle().getSymbolicName()))
				containerMap.put(event.getBundle().getSymbolicName(), new BundleContainer(context, event.getBundle()));
			break;
//		case BundleEvent.UNINSTALLED:
//			containerMap.remove(event.getBundle().getSymbolicName());
		}
		
	}
}
